既存の環境からterraformのファイルを出力するterraformerを使ってみた
既存のAWS環境をエクスポートしてTerraformにまとめたい。
そんなことありませんか。
既存のAWS環境を元にtfファイルとtfstateファイルを出力してくれるterraformerというツールが最近出ました。
GoogleCloudPlatformが中心となって開発しており、GCPのみならず、既存のAWS、GitHub、Datadog、GitHub、Kubernetesの環境にも対応しています。
インストール方法
macOSでは、homebrew
経由でのインストールが既に可能です。
また、goで書かれているので直接ビルドすることも可能です。
下記にビルドする方法を記載しておきます。
$ git clone https://github.com/GoogleCloudPlatform/terraformer.git $ GO111MODULE=on go mod vendor $ go build -v
使用方法
AWSではこのように使用します。
使用可能なサービス一覧はREADMEに記載があります。
VPCやEC2、ALB、RDSなどといった主要なサービスは既にサポートされています。
$ echo 'provider "aws" {}' > init.tf $ terraform init $ terraformer import aws --resources=vpc,subnet --connect=true --regions=eu-west-1 $ terraformer import aws --resources=vpc,subnet --filter=aws_vpc=vpc_id1:vpc_id2:vpc_id3 --regions=eu-west-1 # https://github.com/GoogleCloudPlatform/terraformer#use-with-aws
GCPではこのように使用します。
使用可能なサービス一覧はREADMEに記載があります。
$ echo 'provider "gcp" {}' > init.tf $ terraform init $ terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --connect=true --zone=europe-west1-a --projects=aaa,fff $ terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --filter=google_compute_firewall=rule1:rule2:rule3 --zone=europe-west1-a --projects=aaa,fff # https://github.com/GoogleCloudPlatform/terraformer#use-with-gcp
AWS環境での検証
v0.7.5段階での内容ですが注意点があります。
現在terraformerはAWS CLIのプロファイルに対応していません。
なので認証情報を下記のようにして渡す必要があります。
export AWS_ACCESS_KEY_ID=xxx
、export AWS_SECRET_ACCESS_KEY=xxx
といった形で環境変数を通じて渡す- assume-roleを使用して下記のように実行する
$ assume-role your_profile terraformer import aws --resources=vpc,subnet --connect=true --regions=eu-west-1
実行環境
- terraform : v0.12.2
- terraformer : v0.7.5
- OS : macOS
やってみた
バージニア北部にEC2とALBを構築してその内容をエクスポートしてみました。
terraformerの使用前にterraformにproviderの情報を渡す必要があるのでinit.tf
というファイルを作成して初期化します。
$ echo 'provider "aws" {}' > init.tf $ terraform init
ここまでできたらterraformerを実行します。
$ export AWS_ACCESS_KEY_ID=xxx $ export AWS_SECRET_ACCESS_KEY=xxx $ terraformer import aws \ --resources=vpc,subnet,igw,sg,alb,ec2_instance \ --filter=aws_vpc=id1:vpc-xxxxxxxxxxxxxxxxx \ --regions=us-east-1 2019/07/02 10:31:47 aws importing region us-east-1 2019/07/02 10:31:47 aws importing... vpc 2019/07/02 10:31:57 Refreshing state... aws_vpc.vpc-xxxxxxxxxxxxxxxxx 2019/07/02 10:32:04 aws importing... subnet 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxxxxxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx 2019/07/02 10:32:11 Refreshing state... aws_subnet.subnet-xxxxxxxx ... ...
terraformer aws import
を実行するとターミナルへの出力の後にgenerated
というディレクトリが生成されます。
その中にterraform関連のファイルが出来上がっており、terraform用のファイルが入っています。
terraform.tfstate
や、*.tf
といったファイルが確認できます。
ディレクトリ構造はこのような形になっています。
$ tree generated/ | head -n 20 generated/ └── aws ├── alb │ └── us-east-1 │ ├── lb.tf │ ├── lb_listener.tf │ ├── lb_listener_rule.tf │ ├── lb_target_group.tf │ ├── lb_target_group_attachment.tf │ ├── outputs.tf │ ├── provider.tf │ ├── terraform.tfstate │ └── variables.tf ├── ec2_instance │ └── us-east-1 │ ├── instance.tf │ ├── outputs.tf │ ├── provider.tf │ └── terraform.tfstate ├── igw
tfファイルの中身はこのようになっています。
terraformerでエクスポートしたVPCに紐づくsubnetに関してはハードコーディングされずに出力されています。
逆にエクスポートしなかったデフォルトのVPCに紐づくsubnetに関してはハードコーディングされてしまっています。
resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" { assign_ipv6_address_on_creation = false cidr_block = "192.168.1.0/24" map_public_ip_on_launch = false tags { Name = "terraformer-test-pub-2" } vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}" } resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" { assign_ipv6_address_on_creation = false cidr_block = "192.168.3.0/24" map_public_ip_on_launch = false tags { Name = "terraformer-test-private-2" } vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}" } resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" { assign_ipv6_address_on_creation = false cidr_block = "192.168.0.0/24" map_public_ip_on_launch = false tags { Name = "terraformer-test-pub-1" } vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}" } resource "aws_subnet" "subnet-xxxxxxxxxxxxxxxxx" { assign_ipv6_address_on_creation = false cidr_block = "192.168.2.0/24" map_public_ip_on_launch = false tags { Name = "terraformer-test-private-1" } vpc_id = "${data.terraform_remote_state.vpc.aws_vpc_vpc-xxxxxxxxxxxxxxxxx_id}" } resource "aws_subnet" "subnet-xxxxxxxx" { assign_ipv6_address_on_creation = false cidr_block = "172.31.16.0/20" map_public_ip_on_launch = true tags {} vpc_id = "vpc-xxxxxxxx" } resource "aws_subnet" "subnet-xxxxxxxx" { assign_ipv6_address_on_creation = false cidr_block = "172.31.48.0/20" map_public_ip_on_launch = true tags {} vpc_id = "vpc-xxxxxxxx" } ~~~
また、EC2に関してはVPC、SGなどがハードコーディングされてしまっています。
resource "aws_instance" "i-xxxxxxxxxxxxxxxxx_erraformer-test-1" { ami = "ami-0b898040803850657" associate_public_ip_address = false availability_zone = "us-east-1a" cpu_core_count = "1" cpu_threads_per_core = "1" credit_specification { cpu_credits = "standard" } disable_api_termination = false ebs_optimized = false get_password_data = false iam_instance_profile = "SSM_for_EC2" instance_type = "t2.micro" ipv6_address_count = "0" key_name = "terraformer-test" monitoring = false private_ip = "192.168.2.230" root_block_device { delete_on_termination = true iops = "100" volume_size = "8" volume_type = "gp2" } source_dest_check = true subnet_id = "subnet-xxxxxxxxxxxxxxxxx" tags { Name = "erraformer-test-1" } tenancy = "default" volume_tags { name = "erraformer-test-1" } vpc_security_group_ids = ["sg-xxxxxxxxxxxxxxxxx"] }
さいごに
既存の環境をエクスポートできるのでIaCへの移行が少し容易になるかもしれません。
まだベータ版ということもあり機能面ではまだまだ改良されていきそうなので今後が楽しみですね。